package com.smart.community.work.controller;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.smart.community.commons.annotation.ApiLog;
import com.smart.community.commons.enums.ApiLogOperationType;
import com.smart.community.commons.result.Result;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.work.entity.Attendance;
import com.smart.community.work.service.AttendanceService;
import com.smart.community.work.vo.AttendanceVO;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 考勤管理控制器
 * 
 * 严格按照《Java后端SpringBoot代码开发规范_重构版.md》Controller规范实现：
 * - 统一返回格式：使用Result统一包装返回结果
 * - 参数验证：使用@Valid注解进行参数验证
 * - 异常处理：使用统一的异常处理机制，异常往外抛
 * - 日志记录：记录关键操作日志，避免Controller层log.error
 * - 权限控制：使用SecurityUtils获取当前用户信息
 * - 完整注释：所有接口都有完整的Swagger文档注释
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/work/attendance")
@RequiredArgsConstructor
@Validated
@Tag(name = "考勤管理", description = "考勤管理相关接口")
public class AttendanceController {

    private final AttendanceService attendanceService;

    @GetMapping("/page")
    @Operation(summary = "分页查询考勤记录", description = "分页查询考勤记录列表")
    public Result<IPage<AttendanceVO>> selectAttendancePage(
            @Parameter(description = "分页参数") Page<AttendanceVO> page, 
            @Parameter(description = "查询参数") @RequestParam Map<String, Object> params) throws Exception {
        log.info("开始分页查询考勤记录，当前页：{}，每页大小：{}", page.getCurrent(), page.getSize());
        
        IPage<AttendanceVO> result = attendanceService.selectAttendancePage(page, params);
        log.info("分页查询考勤记录成功，返回记录数：{}", result.getRecords().size());
        return Result.success("查询成功", result);
    }

    @GetMapping("/user/{userId}")
    @Operation(summary = "根据用户ID查询考勤记录", description = "根据用户ID查询考勤记录")
    public Result<List<AttendanceVO>> selectByUserId(
            @Parameter(description = "用户ID", required = true) @PathVariable @NotNull Long userId, 
            @Parameter(description = "开始日期") @RequestParam(required = false) LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) LocalDate endDate) throws Exception {
        log.info("开始根据用户ID查询考勤记录，用户ID：{}，开始日期：{}，结束日期：{}", userId, startDate, endDate);
        
        // 参数校验
        if (userId == null || userId <= 0) {
            return Result.fail("用户ID必须大于0");
        }
        
        // 日期范围校验
        if (startDate != null && endDate != null && startDate.isAfter(endDate)) {
            return Result.fail("开始日期不能晚于结束日期");
        }
        
        List<AttendanceVO> result = attendanceService.selectByUserId(userId, startDate, endDate);
        log.info("根据用户ID查询考勤记录成功，返回记录数：{}", result.size());
        return Result.success("查询成功", result);
    }

    @ApiLog(
        logTitle = "员工上班打卡",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.ADD
    )
    @PostMapping("/clock-in")
    @Operation(summary = "员工上班打卡", description = "员工上班打卡")
    public Result<Boolean> clockIn(@Parameter(description = "考勤信息", required = true) @Valid @RequestBody Attendance attendance) throws Exception {
        log.info("开始员工上班打卡，用户ID：{}", attendance.getUserId());
        
        // 参数校验
        if (attendance.getUserId() == null || attendance.getUserId() <= 0) {
            return Result.fail("用户ID不能为空且必须大于0");
        }
        
        // 权限控制：获取当前用户信息
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            return Result.fail("用户未登录");
        }
        
        Boolean result = attendanceService.clockIn(attendance);
        log.info("员工上班打卡成功，用户ID：{}，结果：{}", attendance.getUserId(), result);
        return Result.success("上班打卡成功", result);
    }

    @ApiLog(
        logTitle = "员工下班打卡",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.ADD
    )
    @PostMapping("/clock-out")
    @Operation(summary = "员工下班打卡", description = "员工下班打卡")
    public Result<Boolean> clockOut(@Parameter(description = "考勤信息", required = true) @Valid @RequestBody Attendance attendance) throws Exception {
        log.info("开始员工下班打卡，用户ID：{}", attendance.getUserId());
        
        // 参数校验
        if (attendance.getUserId() == null || attendance.getUserId() <= 0) {
            return Result.fail("用户ID不能为空且必须大于0");
        }
        
        // 权限控制：获取当前用户信息
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            return Result.fail("用户未登录");
        }
        
        Boolean result = attendanceService.clockOut(attendance);
        log.info("员工下班打卡成功，用户ID：{}，结果：{}", attendance.getUserId(), result);
        return Result.success("下班打卡成功", result);
    }

    @GetMapping("/statistics")
    @Operation(summary = "统计考勤数据", description = "统计考勤数据")
    public Result<Map<String, Object>> getAttendanceStatistics(
            @Parameter(description = "物业公司ID", required = true) @RequestParam @NotNull Long propertyCompanyId,
            @Parameter(description = "开始日期", required = true) @RequestParam @NotNull LocalDate startDate,
            @Parameter(description = "结束日期", required = true) @RequestParam @NotNull LocalDate endDate) throws Exception {
        log.info("开始统计考勤数据，物业公司ID：{}，开始日期：{}，结束日期：{}", propertyCompanyId, startDate, endDate);
        
        // 参数校验
        if (propertyCompanyId == null || propertyCompanyId <= 0) {
            return Result.fail("物业公司ID必须大于0");
        }
        if (startDate == null || endDate == null) {
            return Result.fail("开始日期和结束日期不能为空");
        }
        if (startDate.isAfter(endDate)) {
            return Result.fail("开始日期不能晚于结束日期");
        }
        
        Map<String, Object> result = attendanceService.getAttendanceStatistics(propertyCompanyId, startDate, endDate);
        log.info("统计考勤数据成功，物业公司ID：{}", propertyCompanyId);
        return Result.success("统计成功", result);
    }

    @ApiLog(
        logTitle = "更新考勤状态",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.UPDATE
    )
    @PutMapping("/{id}/status")
    @Operation(summary = "更新考勤状态", description = "更新考勤状态")
    public Result<Boolean> updateStatus(
            @Parameter(description = "考勤记录ID", required = true) @PathVariable @NotNull Long id, 
            @Parameter(description = "状态", required = true) @RequestParam @NotNull Integer status) throws Exception {
        log.info("开始更新考勤状态，ID：{}，状态：{}", id, status);
        
        // 参数校验
        if (id == null || id <= 0) {
            return Result.fail("考勤记录ID必须大于0");
        }
        if (status == null) {
            return Result.fail("状态不能为空");
        }
        
        Boolean result = attendanceService.updateStatus(id, status, SecurityUtils.getCurrentUserId());
        log.info("更新考勤状态成功，ID：{}，结果：{}", id, result);
        return Result.success("更新成功", result);
    }

    @ApiLog(
        logTitle = "删除考勤记录",
        logType = 2,
        moduleName = "工作管理",
        operationType = ApiLogOperationType.DELETE
    )
    @DeleteMapping("/{id}")
    @Operation(summary = "删除考勤记录", description = "删除考勤记录")
    public Result<Boolean> deleteById(@Parameter(description = "考勤记录ID", required = true) @PathVariable @NotNull Long id) throws Exception {
        log.info("开始删除考勤记录，ID：{}", id);
        
        // 参数校验
        if (id == null || id <= 0) {
            return Result.fail("考勤记录ID必须大于0");
        }
        
        Boolean result = attendanceService.deleteById(id, SecurityUtils.getCurrentUserId());
        log.info("删除考勤记录成功，ID：{}，结果：{}", id, result);
        return Result.success("删除成功", result);
    }
}